import tkinter as tk
from tkinter import ttk
from tkinter import filedialog, messagebox
import pyvista as pv
from scipy.io import loadmat
import numpy as np
var_list=["node_U", "node_F", "el_mises", "el_stress", "el_strain"]
node_U_componnets = ['U1', 'U2', 'U3',"Umag"]
node_F_componnets = ['F1', 'F2', 'F3','Fmag']
mises_componnets = ['Mises']
stress_componnets = ['S11', 'S22', 'S33', 'S12', 'S23', 'S13']
strain_componnets = ['E11', 'E22', 'E33', 'E12', 'E23', 'E13']
el_vars=["el_mises","el_stress","el_strain"]
node_vars=["node_U","node_F"]
Num20=20
Num10=10


class ResultViewer:
    def __init__(self, root):
        self.root = root
        self.root.title("C3D4静力结果查看器")
        self.root.geometry("500x350")
        self.create_widgets()
        self.mesh=pv.UnstructuredGrid()
        self.nodes=None
        self.cells=None
        self.cell_types=None
        self.mesh_data={}
        self.Displacement=0
    def import_file(self):
        self.output_text.insert(tk.END, "正在导入mat文件\n")
        mat_path = filedialog.askopenfilename(title="选择mat文件", filetypes=[("mat文件", "*.mat")])
        if not mat_path:
            self.output_text.insert(tk.END, "未选择文件\n")
            return
        try:
            # 读取文件内容
            mat_dats=loadmat(mat_path)
            elem_num=mat_dats['element_num'][0,0]
            vtk_type=mat_dats['vtk_type'][0,0]
            self.nodes=mat_dats['Node_data'][:,1:]
            self.cells=np.concatenate((np.ones((elem_num,1),dtype=int)*4,mat_dats['connecticity_data'][:,1:]-1),axis=1)
            self.cell_types=np.ones(elem_num)*vtk_type
            # 生成网格对象
            self.mesh = pv.UnstructuredGrid(self.cells, self.cell_types, self.nodes)
            self.Displacement=mat_dats["node_displacement"][:,:3]
            # 设置网格数据
            self.mesh.point_data["node_U_U1"]=mat_dats["node_displacement"][:,0]
            self.mesh.point_data["node_U_U2"]=mat_dats["node_displacement"][:,1]
            self.mesh.point_data["node_U_U3"]=mat_dats["node_displacement"][:,2]
            self.mesh.point_data["node_U_Umag"]=mat_dats["node_displacement"][:,3]
            #  ['F1', 'F2', 'F3','Fmag']
            self.mesh.point_data["node_F_F1"]=mat_dats["node_force"][:,0]
            self.mesh.point_data["node_F_F2"]=mat_dats["node_force"][:,1]
            self.mesh.point_data["node_F_F3"]=mat_dats["node_force"][:,2]
            self.mesh.point_data["node_F_Fmag"]=mat_dats["node_force"][:,3]
            # ['S11', 'S22', 'S33', 'S12', 'S23', 'S13']
            self.mesh.cell_data["el_stress_S11"]=mat_dats["element_stress"][:,0]
            self.mesh.cell_data["el_stress_S22"]=mat_dats["element_stress"][:,1]
            self.mesh.cell_data["el_stress_S33"]=mat_dats["element_stress"][:,2]
            self.mesh.cell_data["el_stress_S12"]=mat_dats["element_stress"][:,3]
            self.mesh.cell_data["el_stress_S23"]=mat_dats["element_stress"][:,4]
            self.mesh.cell_data["el_stress_S13"]=mat_dats["element_stress"][:,5]
            self.mesh.cell_data["el_strain_E11"]=mat_dats["element_strain"][:,0]
            self.mesh.cell_data["el_strain_E22"]=mat_dats["element_strain"][:,1]
            self.mesh.cell_data["el_strain_E33"]=mat_dats["element_strain"][:,2]
            self.mesh.cell_data["el_strain_E12"]=mat_dats["element_strain"][:,3]
            self.mesh.cell_data["el_strain_E23"]=mat_dats["element_strain"][:,4]
            self.mesh.cell_data["el_strain_E13"]=mat_dats["element_strain"][:,5]
            self.mesh.cell_data["el_mises_Mises"]=mat_dats["element_mises"][:,0]
            # 输出信息
            self.output_text.insert(tk.END,f"==>成功读取文件:{mat_path}\n")
        except Exception as except_msg:
            self.output_text.insert(tk.END, f"==>导入文件失败:{except_msg}\n")
            return
    def show_mesh_info(self):
        self.output_text.insert(tk.END, "网格信息:\n")
        self.output_text.insert(tk.END, f"节点数:{self.mesh.n_points}\n")
        self.output_text.insert(tk.END, f"单元数:{self.mesh.n_cells}\n")
    def update_cloud(self):
        if self.deformed_grid_var.get():
            grid=self.mesh.copy()
            grid.points=self.mesh.points+self.Displacement*float(self.magnification_entry.get())
        else:
            grid=self.mesh.copy()
        # pv.set_plot_theme('paraview')
        scalars=self.variable_combobox.get()+"_"+self.quantity_combobox.get()
        scalar_bar_args={"title":'',"vertical":True,"interactive":True,}
        kwargs={'scalars':scalars,
                'scalar_bar_args':scalar_bar_args,
                'show_edges':self.show_edges_var.get(),
                'text':scalars,
                'window_size' :[600, 600],}
        if self.line_mode_var.get():
            kwargs['line_width']=5
            kwargs['line_color']='black'
            kwargs['style'] = 'wireframe'
        grid.plot(**kwargs)
        
    def create_widgets(self):
        # 导入文件按钮
        self.import_button = tk.Button(self.root, text="导入文件", command=self.import_file)
        self.import_button.grid(row=0, column=0,padx=Num20, pady=Num20)
        # 更新云图按钮
        self.update_button = tk.Button(self.root, text="更新云图", command=self.update_cloud)
        self.update_button.grid(row=0, column=1,padx=Num20, pady=Num20)
        # 更新云图按钮
        self.infos_button = tk.Button(self.root, text="网格信息", command=self.show_mesh_info)
        self.infos_button.grid(row=0, column=2,padx=Num20, pady=Num20)
        # 选择变量下拉框
        self.variable_label = tk.Label(self.root, text="选择变量")
        self.variable_label.grid(row=1, column=0, padx=Num20, pady=Num10)
        self.variable_combobox = ttk.Combobox(self.root, values=var_list,width=10)
        self.variable_combobox.grid(row=1, column=1, padx=Num20, pady=Num10)
        self.variable_combobox.current(0)
        self.variable_combobox.bind("<<ComboboxSelected>>", self.update_component)
        # 选择分量下拉框
        self.quantity_label = tk.Label(self.root, text="选择分量")
        self.quantity_label.grid(row=1, column=2, padx=Num20, pady=Num10)
        self.quantity_combobox = ttk.Combobox(self.root,values=node_U_componnets,width=10)
        self.quantity_combobox.grid(row=1, column=3,padx=Num20, pady=Num10)
        self.quantity_combobox.current(0)
        # self.quantity_combobox.bind("<<ComboboxSelected>>", self.select_quantity)
        self.label_frame = tk.Label(self.root, text="绘图选项")
        self.label_frame.grid(column=0, row=2)
        
        self.grid_var = tk.IntVar(master=self.root,value=True)
        self.line_mode_var = tk.IntVar(master=self.root,value=False)
        self.normal_mode_var = tk.IntVar(master=self.root,value=False)
        self.show_edges_var = tk.IntVar(master=self.root,value=False)
        self.deformed_grid_var = tk.IntVar(master=self.root,value=False)
        self.only_mesh_var = tk.IntVar(master=self.root,value=True)

        self.grid_check = tk.Checkbutton(self.root, text="非变形网格", variable=self.grid_var)
        self.grid_check.grid(row=4, column=0, padx=Num10, pady=Num10)

        self.line_mode_check = tk.Checkbutton(self.root, text="线框模式", variable=self.line_mode_var)
        self.line_mode_check.grid(row=5, column=1, padx=Num10, pady=Num10)
        self.line_mode_check = tk.Checkbutton(self.root, text="只显示网格", variable=self.only_mesh_var)
        self.line_mode_check.grid(row=5, column=2, padx=Num10, pady=Num10)

        self.show_edges_check = tk.Checkbutton(self.root, text="显示边线", variable=self.show_edges_var)
        self.show_edges_check.grid(row=5, column=0, padx=Num10, pady=Num10)

        self.deformed_grid_check = tk.Checkbutton(self.root, text="变形网格", variable=self.deformed_grid_var)
        self.deformed_grid_check.grid(row=4, column=1, padx=Num10, pady=Num10)
        # 放大系数输入框
        self.magnification_label = tk.Label(self.root, text="放大系数")
        self.magnification_label.grid(row=4, column=2, padx=Num20, pady=Num10)
        self.magnification_entry = tk.Entry(self.root,width=10)
        self.magnification_entry.grid(row=4, column=3, padx=Num20, pady=Num10)
        self.magnification_entry.insert(0, "1.0")
        # self.magnification_entry.bind("<KeyRelease>", self.set_magnification)
        # # 信息输出文本框
        self.output_text = tk.Text(self.root, height=5, width=60)
        self.output_text.grid(row=6, columnspan= 5,column=0, padx=Num10, pady=Num10)

    def update_component(self, event):
        if self.variable_combobox.get() == "node_U":
            self.quantity_combobox.config(values=node_U_componnets)
        elif self.variable_combobox.get() == "node_F":
            self.quantity_combobox.config(values=node_F_componnets)
        elif self.variable_combobox.get() == "el_mises":
            self.quantity_combobox.config(values=mises_componnets)
        elif self.variable_combobox.get() == "el_stress":
            self.quantity_combobox.config(values=stress_componnets)
        elif self.variable_combobox.get() == "el_strains":
            self.quantity_combobox.config(values=strain_componnets)
        self.quantity_combobox.current(0)
if __name__ == "__main__":
    # 创建主窗口并运行
    root = tk.Tk()
    app = ResultViewer(root)
    root.mainloop()